package com.db.common.aop;

import com.db.common.annotation.RequiredDept;
import com.db.common.util.IPUtils;
import com.db.pojo.SysLog;
import com.db.service.SysLogService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Arrays;

@Aspect
@Component
public class SysDeptAspect {

    @Autowired
    private SysLogService sysLogService;

    @Pointcut("bean(sysDeptServiceImpl)")
    public void doAspect() {
    }

    @Around("doAspect()")
    public Object doAround(ProceedingJoinPoint jp) throws Throwable {

        long start = System.currentTimeMillis();
        Object proceed = jp.proceed();
        long end = System.currentTimeMillis();

        saveLog(jp, (end - start));

        return proceed;
    }

    private void saveLog(ProceedingJoinPoint jp, long time) throws NoSuchMethodException {

        SysLog sysLog = new SysLog();
        sysLog.setIp(IPUtils.getIpAddr());
        sysLog.setMethod(getMethod(jp));
        sysLog.setOperation(getOperation(jp));
        sysLog.setParams(Arrays.toString(jp.getArgs()));
        sysLog.setTime(time);
        sysLog.setUsername("admin");

        sysLogService.insertObject(sysLog);
    }

    private String getMethod(ProceedingJoinPoint jp) {
        Class<?> clazz = jp.getTarget().getClass();
        String className = clazz.getName();
        Signature signature = jp.getSignature();
        String methodName = signature.getName();
        return className + "." + methodName;
    }

    private String getOperation(ProceedingJoinPoint jp) throws NoSuchMethodException {
        Class<?> clazz = jp.getTarget().getClass();
        MethodSignature signature = (MethodSignature) jp.getSignature();
        Method method = clazz.getMethod(signature.getName(), signature.getParameterTypes());
        RequiredDept annotation = method.getAnnotation(RequiredDept.class);
        if (annotation == null)
            return "operation";
        return annotation.operation();
    }
}
